﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Swift;
using Utils;


namespace OBJ {
    public class GameObjectFactory {
        public static CoroutineManager CM;
        

        IEnumerator move(Tank o, int tx, int ty) {

            float x = o.X == tx ? 0 : ((o.X < tx) ? o.Speed : -o.Speed);
            float y = o.Y == ty ? 0 : ((o.Y < ty) ? o.Speed : -o.Speed);

            while(o.X != tx || o.Y != ty) {
                o.Mov (x, y);



                yield return new TimeWaiter (10);
            }

            yield return null;
        }

        public void Move(Tank o, int tx, int ty) {
            icList.AddLast(CM.Start (move(o, tx, ty)));
        }

        #region 提供碰撞检查的功能

        /// <summary>
        /// 判断 a 是否遇到障碍，如果遇到障碍，进行回调，回调返回 true，调整 a 的位置为当前方向最接近障碍的地方。
        /// </summary>
        /// <param name="a"></param>
        /// <param name="callback"></param>
        /// <returns></returns>
        public bool IsBlock(GameObject a, Func<GameObject, bool> callback) {

            if(a.GetX () < CoordinateUtil.MinX + a.Size / 2) {  // 上下边界
                a.SetX (CoordinateUtil.MinX + a.Size / 2);
                return true;
            } else if(a.GetX () > CoordinateUtil.MaxX - a.Size / 2) {
                a.SetX (CoordinateUtil.MaxX - a.Size / 2);
                return true;
            }

            if(a.GetY () < CoordinateUtil.MinY + a.Size / 2) {  // 左右边界
                a.SetY (CoordinateUtil.MinY + a.Size / 2);
                return true;
            } else if(a.GetY () > CoordinateUtil.MaxY - a.Size / 2) {
                a.SetY (CoordinateUtil.MaxY - a.Size / 2);
                return true;
            }

            foreach(GameObject o in objects) {
                if(a == o || a == o.Owner || o.Owner == a || a.Owner != null && o.Owner != null && a.Owner.Tag.Equals (o.Owner.Tag)) {
                    // a 、o 是同一物件，或 a 、o 有关系
                    continue;
                }

                if(o.Tag == "grass") {       // 草地对坦克来说不是障碍
                    continue;
                }

                if(IsOverlapped (a, o)) {    // 有重叠

                    if(!callback (o)) {      // 有重叠需要判断的不一定都是障碍，有可能是食物
                        continue;
                    }

                    if(a.Dir == DIR.UP) {
                        a.SetX (o.GetSX () - a.Size + a.Size / 2);
                    } else if(a.Dir == DIR.DOWN) {
                        a.SetX (o.GetSX () + o.Size + a.Size / 2);
                    } else if(a.Dir == DIR.LEFT) {
                        a.SetY (o.GetSY () + o.Size + a.Size / 2);
                    } else {
                        a.SetY (o.GetSY () - a.Size + a.Size / 2);
                    }

                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 检查actor 是否发生碰撞，并且返回所有障碍，用于子弹
        /// </summary>
        /// <param name="a"></param>
        /// <param name="obstacles"></param>
        /// <returns></returns>
        public bool IsBlock(GameObject actor, out List<GameObject> obstacles) {
            List<GameObject> res = new List<GameObject> ();
            obstacles = res;

            if(actor.GetX () < CoordinateUtil.MinX + actor.Size / 2) {  // 上下边界
                return true;
            } else if(actor.GetX () > CoordinateUtil.MaxX - actor.Size / 2) {
                return true;
            }

            if(actor.GetY () < CoordinateUtil.MinY + actor.Size / 2) {  // 左右边界
                return true;
            } else if(actor.GetY () > CoordinateUtil.MaxY - actor.Size / 2) {
                return true;
            }

            foreach(GameObject a in objects) {

                if(a == actor || a == actor.Owner || a.Owner == actor || a.Owner != null && actor.Owner != null && a.Owner.Tag.Equals (actor.Owner.Tag)) {
                    continue;
                }

                if(a.Tag == "grass")
                    continue;
                if(a.Tag == "water")
                    continue;
                if(a.Tag == "slide")
                    continue;
                if(a.Tag == "food")
                    continue;

                if(IsOverlapped (actor, a)) {
                    res.Add (a);
                }
            }

            if(obstacles.Count > 0) {
                return true;
            } else {
                return false;
            }
        }

        /// <summary>
        /// 判断 c、d 是否重叠，通过 b 的四个角是否在 a 所占据的矩形内判断，（b是c、d中较小者，a是c、d中较大者）
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public bool IsOverlapped(GameObject c, GameObject d) {

            GameObject a, b;
            if(c.Size > d.Size) {
                a = c;
                b = d;
            } else {
                a = d;
                b = c;
            }

            if(CoordinateUtil.IsInSquare (a.GetSX (), a.GetSY (), a.Size, b.GetSX () + CoordinateUtil.EPS, b.GetSY () + CoordinateUtil.EPS))
                return true;
            else if(CoordinateUtil.IsInSquare (a.GetSX (), a.GetSY (), a.Size, b.GetSX () + b.Size - CoordinateUtil.EPS, b.GetSY () + CoordinateUtil.EPS))
                return true;
            else if(CoordinateUtil.IsInSquare (a.GetSX (), a.GetSY (), a.Size, b.GetSX () + CoordinateUtil.EPS, b.GetSY () + b.Size - CoordinateUtil.EPS))
                return true;
            else if(CoordinateUtil.IsInSquare (a.GetSX (), a.GetSY (), a.Size, b.GetSX () + b.Size - CoordinateUtil.EPS, b.GetSY () + b.Size - CoordinateUtil.EPS))
                return true;

            return false;
        }

        #endregion

        #region 保护成员

        LinkedList<ICoroutine> icList = new LinkedList<ICoroutine> ();
        LinkedList<GameObject> objects = new LinkedList<GameObject> ();


        #endregion
    }
}
